# coding:utf-8
#
# The MIT License (MIT)
#
# Copyright (c) 2016-2019 yutiansut/QUANTAXIS
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from functools import reduce

import numpy as np
import pandas as pd

from QUANTAXIS.QAIndicator.base import *

"""
DataFrame 类

以下的函数都可以被直接add_func


"""

"""
1.	趋向指标 
又叫趋势跟踪类指标,主要用于跟踪并预测股价的发展趋势

包含的主要指标
1. 移动平均线 MA
2. 指数平滑移动平均线 MACD
3. 趋向指标 DMI
4. 瀑布线 PBX
5. 平均线差 DMA
6. 动力指标(动量线)  MTM
7. 指数平均线 EXPMA
8. 佳庆指标 CHO
"""


def QA_indicator_MA(DataFrame, *args, **kwargs):
    """MA

    Arguments:
        DataFrame {[type]} -- [description]

    Returns:
        [type] -- [description]
    """

    CLOSE = DataFrame['close']
    return pd.DataFrame({'MA{}'.format(N): MA(CLOSE, N) for N in list(args)})


def QA_indicator_EMA(DataFrame, N):
    CLOSE = DataFrame['close']
    return pd.DataFrame({'EMA': EMA(CLOSE, N)})


def QA_indicator_SMA(DataFrame, N):
    CLOSE = DataFrame['close']
    return pd.DataFrame({'SMA': SMA(CLOSE, N)})


def QA_indicator_MACD(DataFrame, short=9, long=26, mid=12):
    """
    MACD CALC
    """
    CLOSE = DataFrame['close']
    DIF = EMA(CLOSE, short) - EMA(CLOSE, long)
    DEA = EMA(DIF, mid)
    MACD = (DIF - DEA) * 2

    # UP = QA.IFAND(QA.LLV(DEA, N=M) > 0, QA.LLV(DIFF, N=M) > 0, 1, 0)
    # CROSS_JC = QA.IFAND(QA.CROSS(DIFF, DEA), UP, 1, 0)
    JC = CROSS(DIF, DEA)  # 金叉
    SC = CROSS(DEA, DIF)  # 死叉

    return pd.DataFrame({'close': CLOSE, 'DIF': DIF, 'DEA': DEA, 'MACD': MACD, 'JC': JC, 'SC': SC})


def QA_indicator_DMI(DataFrame, M1=14, M2=6):
    """
    趋向指标 DMI
    """
    HIGH = DataFrame.high
    LOW = DataFrame.low
    CLOSE = DataFrame.close
    OPEN = DataFrame.open

    TR = SUM(MAX(MAX(HIGH - LOW, ABS(HIGH - REF(CLOSE, 1))),
                 ABS(LOW - REF(CLOSE, 1))), M1)
    HD = HIGH - REF(HIGH, 1)
    LD = REF(LOW, 1) - LOW
    DMP = SUM(IFAND(HD > 0, HD > LD, HD, 0), M1)
    DMM = SUM(IFAND(LD > 0, LD > HD, LD, 0), M1)
    DI1 = DMP * 100 / TR
    DI2 = DMM * 100 / TR
    ADX = MA(ABS(DI2 - DI1) / (DI1 + DI2) * 100, M2)
    ADXR = (ADX + REF(ADX, M2)) / 2

    return pd.DataFrame({
        'DI1': DI1, 'DI2': DI2,
        'ADX': ADX, 'ADXR': ADXR
    })


def QA_indicator_PBX(DataFrame, N1=3, N2=5, N3=8, N4=13, N5=18, N6=24):
    '瀑布线'
    C = DataFrame['close']
    PBX1 = (EMA(C, N1) + EMA(C, 2 * N1) + EMA(C, 4 * N1)) / 3
    PBX2 = (EMA(C, N2) + EMA(C, 2 * N2) + EMA(C, 4 * N2)) / 3
    PBX3 = (EMA(C, N3) + EMA(C, 2 * N3) + EMA(C, 4 * N3)) / 3
    PBX4 = (EMA(C, N4) + EMA(C, 2 * N4) + EMA(C, 4 * N4)) / 3
    PBX5 = (EMA(C, N5) + EMA(C, 2 * N5) + EMA(C, 4 * N5)) / 3
    PBX6 = (EMA(C, N6) + EMA(C, 2 * N6) + EMA(C, 4 * N6)) / 3
    DICT = {'PBX1': PBX1, 'PBX2': PBX2, 'PBX3': PBX3,
            'PBX4': PBX4, 'PBX5': PBX5, 'PBX6': PBX6}

    return pd.DataFrame(DICT)


def QA_indicator_DMA(DataFrame, M1=10, M2=50, M3=10):
    """
    平均线差 DMA
    """
    CLOSE = DataFrame.close
    DDD = MA(CLOSE, M1) - MA(CLOSE, M2)
    AMA = MA(DDD, M3)
    return pd.DataFrame({
        'DDD': DDD, 'AMA': AMA
    })


def QA_indicator_MTM(DataFrame, N=12, M=6):
    '动量线'
    C = DataFrame.close
    mtm = C - REF(C, N)
    MTMMA = MA(mtm, M)
    DICT = {'MTM': mtm, 'MTMMA': MTMMA}

    return pd.DataFrame(DICT)


def QA_indicator_EXPMA(DataFrame, P1=5, P2=10, P3=20, P4=60):
    """ 指数平均线 EXPMA"""
    CLOSE = DataFrame.close
    MA1 = EMA(CLOSE, P1)
    MA2 = EMA(CLOSE, P2)
    MA3 = EMA(CLOSE, P3)
    MA4 = EMA(CLOSE, P4)
    return pd.DataFrame({
        'MA1': MA1, 'MA2': MA2, 'MA3': MA3, 'MA4': MA4
    })


def QA_indicator_CHO(DataFrame, N1=10, N2=20, M=6):
    """
    佳庆指标 CHO
    """
    HIGH = DataFrame.high
    LOW = DataFrame.low
    CLOSE = DataFrame.close
    VOL = DataFrame.volume
    MID = SUM(VOL * (2 * CLOSE - HIGH - LOW) / (HIGH + LOW), 0)
    CHO = MA(MID, N1) - MA(MID, N2)
    MACHO = MA(CHO, M)
    return pd.DataFrame({
        'CHO': CHO, 'MACHO': MACHO
    })


"""

2.	反趋向指标
主要捕捉趋势的转折点

随机指标KDJ
乖离率 BIAS
变动速率 ROC
顺势指标 CCI
威廉指标 W&R
震荡量(变动速率) OSC
相对强弱指标 RSI
动态买卖指标 ADTM

"""


def QA_indicator_KDJ(DataFrame, N=9, M1=3, M2=3):
    C = DataFrame['close']
    H = DataFrame['high']
    L = DataFrame['low']

    RSV = (C - LLV(L, N)) / (HHV(H, N) - LLV(L, N)) * 100
    K = SMA(RSV, M1)
    D = SMA(K, M2)
    J = 3 * K - 2 * D
    DICT = {'KDJ_K': K, 'KDJ_D': D, 'KDJ_J': J}
    return pd.DataFrame(DICT)


def QA_indicator_BIAS(DataFrame, N1, N2, N3):
    '乖离率'
    CLOSE = DataFrame['close']
    BIAS1 = (CLOSE - MA(CLOSE, N1)) / MA(CLOSE, N1) * 100
    BIAS2 = (CLOSE - MA(CLOSE, N2)) / MA(CLOSE, N2) * 100
    BIAS3 = (CLOSE - MA(CLOSE, N3)) / MA(CLOSE, N3) * 100
    DICT = {'BIAS1': BIAS1, 'BIAS2': BIAS2, 'BIAS3': BIAS3}

    return pd.DataFrame(DICT)


def QA_indicator_ROC(DataFrame, N=12, M=6):
    '变动率指标'
    C = DataFrame['close']
    roc = 100 * (C - REF(C, N)) / REF(C, N)
    ROCMA = MA(roc, M)
    DICT = {'ROC': roc, 'ROCMA': ROCMA}

    return pd.DataFrame(DICT)


def QA_indicator_CCI(DataFrame, N=14):
    """
    TYP:=(HIGH+LOW+CLOSE)/3;
    CCI:(TYP-MA(TYP,N))/(0.015*AVEDEV(TYP,N));
    """
    typ = (DataFrame['high'] + DataFrame['low'] + DataFrame['close']) / 3
    cci = ((typ - MA(typ, N)) / (0.015 * AVEDEV(typ, N)))
    a = 100
    b = -100

    return pd.DataFrame({
        'CCI': cci, 'a': a, 'b': b
    })


def QA_indicator_WR(DataFrame, N, N1):
    '威廉指标'
    HIGH = DataFrame['high']
    LOW = DataFrame['low']
    CLOSE = DataFrame['close']
    WR1 = 100 * (HHV(HIGH, N) - CLOSE) / (HHV(HIGH, N) - LLV(LOW, N))
    WR2 = 100 * (HHV(HIGH, N1) - CLOSE) / (HHV(HIGH, N1) - LLV(LOW, N1))
    DICT = {'WR1': WR1, 'WR2': WR2}

    return pd.DataFrame(DICT)


def QA_indicator_OSC(DataFrame, N=20, M=6):
    """变动速率线

    震荡量指标OSC，也叫变动速率线。属于超买超卖类指标,是从移动平均线原理派生出来的一种分析指标。

    它反应当日收盘价与一段时间内平均收盘价的差离值,从而测出股价的震荡幅度。

    按照移动平均线原理，根据OSC的值可推断价格的趋势，如果远离平均线，就很可能向平均线回归。
    """
    C = DataFrame['close']
    OS = (C - MA(C, N)) * 100
    MAOSC = EMA(OS, M)
    DICT = {'OSC': OS, 'MAOSC': MAOSC}

    return pd.DataFrame(DICT)


def QA_indicator_RSI(DataFrame, N1=12, N2=26, N3=9):
    '相对强弱指标RSI1:SMA(MAX(CLOSE-LC,0),N1,1)/SMA(ABS(CLOSE-LC),N1,1)*100;'
    CLOSE = DataFrame['close']
    LC = REF(CLOSE, 1)
    RSI1 = SMA(MAX(CLOSE - LC, 0), N1) / SMA(ABS(CLOSE - LC), N1) * 100
    RSI2 = SMA(MAX(CLOSE - LC, 0), N2) / SMA(ABS(CLOSE - LC), N2) * 100
    RSI3 = SMA(MAX(CLOSE - LC, 0), N3) / SMA(ABS(CLOSE - LC), N3) * 100
    DICT = {'RSI1': RSI1, 'RSI2': RSI2, 'RSI3': RSI3}

    return pd.DataFrame(DICT)


def QA_indicator_ADTM(DataFrame, N=23, M=8):
    '动态买卖气指标'
    HIGH = DataFrame.high
    LOW = DataFrame.low
    OPEN = DataFrame.open
    DTM = IF(OPEN > REF(OPEN, 1), MAX((HIGH - OPEN), (OPEN - REF(OPEN, 1))), 0)
    DBM = IF(OPEN < REF(OPEN, 1), MAX((OPEN - LOW), (OPEN - REF(OPEN, 1))), 0)
    STM = SUM(DTM, N)
    SBM = SUM(DBM, N)
    ADTM1 = IF(STM > SBM, (STM - SBM) / STM,
               IF(STM != SBM, (STM - SBM) / SBM, 0))
    MAADTM = MA(ADTM1, M)
    DICT = {'ADTM': ADTM1, 'MAADTM': MAADTM}

    return pd.DataFrame(DICT)


"""
3.	量能指标
通过成交量的大小和变化研判趋势变化
容量指标 VR
量相对强弱 VRSI
能量指标 CR
人气意愿指标 ARBR
成交量标准差 VSTD"""


def QA_indicator_VR(DataFrame, M1=26, M2=100, M3=200):
    VOL = DataFrame.volume
    CLOSE = DataFrame.close
    LC = REF(CLOSE, 1)
    VR = SUM(IF(CLOSE > LC, VOL, 0), M1) / SUM(IF(CLOSE <= LC, VOL, 0), M1) * 100
    a = M2
    b = M3
    return pd.DataFrame({
        'VR': VR, 'a': a, 'b': b
    })


def QA_indicator_VRSI(DataFrame, N=6):
    VOL = DataFrame.volume
    vrsi = SMA(MAX(VOL - REF(VOL, 1), 0), N, 1) / \
           SMA(ABS(VOL - REF(VOL, 1)), N, 1) * 100

    return pd.DataFrame({'VRSI': vrsi})


def QA_indicator_CR(DataFrame, N=26, M1=5, M2=10, M3=20):
    HIGH = DataFrame.high
    LOW = DataFrame.low
    CLOSE = DataFrame.close
    VOL = DataFrame.volume
    MID = (HIGH + LOW + CLOSE) / 3

    CR = SUM(MAX(0, HIGH - REF(MID, 1)), N) / SUM(MAX(0, REF(MID, 1) - LOW), N) * 100
    MA1 = REF(MA(CR, M1), M1 / 2.5 + 1)
    MA2 = REF(MA(CR, M2), M2 / 2.5 + 1)
    MA3 = REF(MA(CR, M3), M3 / 2.5 + 1)
    return pd.DataFrame({
        'CR': CR, 'MA1': MA1, 'MA2': MA2, 'MA3': MA3
    })


def QA_indicator_ARBR(DataFrame, M1=26, M2=70, M3=150):
    HIGH = DataFrame.high
    LOW = DataFrame.low
    CLOSE = DataFrame.close
    OPEN = DataFrame.open
    AR = SUM(HIGH - OPEN, M1) / SUM(OPEN - LOW, M1) * 100
    BR = SUM(MAX(0, HIGH - REF(CLOSE, 1)), M1) / \
         SUM(MAX(0, REF(CLOSE, 1) - LOW), M1) * 100
    a = M2
    b = M3
    return pd.DataFrame({
        'AR': AR, 'BR': BR, 'a': a, 'b': b
    })


def QA_indicator_VSTD(DataFrame, N=10):
    VOL = DataFrame.volume
    vstd = STD(VOL, N)
    return pd.DataFrame({'VSTD': vstd})


"""
4.	量价指标
通过成交量和股价变动关系分析未来趋势
震荡升降指标ASI
价量趋势PVT
能量潮OBV
量价趋势VPT
"""


def QA_indicator_ASI(DataFrame, M1=26, M2=10):
    """
    LC=REF(CLOSE,1);
    AA=ABS(HIGH-LC);
    BB=ABS(LOW-LC);
    CC=ABS(HIGH-REF(LOW,1));
    DD=ABS(LC-REF(OPEN,1));
    R=IF(AA>BB AND AA>CC,AA+BB/2+DD/4,IF(BB>CC AND BB>AA,BB+AA/2+DD/4,CC+DD/4));
    X=(CLOSE-LC+(CLOSE-OPEN)/2+LC-REF(OPEN,1));
    SI=16*X/R*MAX(AA,BB);
    ASI:SUM(SI,M1);
    ASIT:MA(ASI,M2);
    """
    CLOSE = DataFrame['close']
    HIGH = DataFrame['high']
    LOW = DataFrame['low']
    OPEN = DataFrame['open']
    LC = REF(CLOSE, 1)
    AA = ABS(HIGH - LC)
    BB = ABS(LOW - LC)
    CC = ABS(HIGH - REF(LOW, 1))
    DD = ABS(LC - REF(OPEN, 1))

    R = IFAND(AA > BB, AA > CC, AA + BB / 2 + DD / 4,
              IFAND(BB > CC, BB > AA, BB + AA / 2 + DD / 4, CC + DD / 4))
    X = (CLOSE - LC + (CLOSE - OPEN) / 2 + LC - REF(OPEN, 1))
    SI = 16 * X / R * MAX(AA, BB)
    ASI = SUM(SI, M1)
    ASIT = MA(ASI, M2)
    return pd.DataFrame({
        'ASI': ASI, 'ASIT': ASIT
    })


def QA_indicator_PVT(DataFrame):
    CLOSE = DataFrame.close
    VOL = DataFrame.volume
    PVT = SUM((CLOSE - REF(CLOSE, 1)) / REF(CLOSE, 1) * VOL, 0)
    return pd.DataFrame({'PVT': PVT})


def QA_indicator_OBV(DataFrame):
    """能量潮"""
    VOL = DataFrame.volume
    CLOSE = DataFrame.close
    return pd.DataFrame({
        'OBV': np.cumsum(IF(CLOSE > REF(CLOSE, 1), VOL, IF(CLOSE < REF(CLOSE, 1), -VOL, 0))) / 10000
    })


def QA_indicator_VPT(DataFrame, N=51, M=6):
    VOL = DataFrame.volume
    CLOSE = DataFrame.close
    VPT = SUM(VOL * (CLOSE - REF(CLOSE, 1)) / REF(CLOSE, 1), 0)
    MAVPT = MA(VPT, M)
    return pd.DataFrame({
        'VPT': VPT, 'MAVPT': MAVPT
    })


"""
5.	压力支撑指标
主要用于分析股价目前收到的压力和支撑
布林带 BOLL
麦克指标 MIKE
"""


def QA_indicator_BOLL(DataFrame, N=20, P=2):
    '布林线'
    C = DataFrame['close']
    boll = MA(C, N)
    UB = boll + P * STD(C, N)
    LB = boll - P * STD(C, N)
    DICT = {'BOLL': boll, 'UB': UB, 'LB': LB}

    return pd.DataFrame(DICT)


def QA_indicator_MIKE(DataFrame, N=12):
    """
    MIKE指标
    指标说明
    MIKE是另外一种形式的路径指标。
    买卖原则
    1  WEAK-S，MEDIUM-S，STRONG-S三条线代表初级、中级、强力支撑。
    2  WEAK-R，MEDIUM-R，STRONG-R三条线代表初级、中级、强力压力。
    """
    HIGH = DataFrame.high
    LOW = DataFrame.low
    CLOSE = DataFrame.close

    TYP = (HIGH + LOW + CLOSE) / 3
    LL = LLV(LOW, N)
    HH = HHV(HIGH, N)

    WR = TYP + (TYP - LL)
    MR = TYP + (HH - LL)
    SR = 2 * HH - LL
    WS = TYP - (HH - TYP)
    MS = TYP - (HH - LL)
    SS = 2 * LL - HH
    return pd.DataFrame({
        'WR': WR, 'MR': MR, 'SR': SR,
        'WS': WS, 'MS': MS, 'SS': SS
    })


def QA_indicator_BBI(DataFrame, N1=3, N2=6, N3=12, N4=24):
    '多空指标'
    C = DataFrame['close']
    bbi = (MA(C, N1) + MA(C, N2) + MA(C, N3) + MA(C, N4)) / 4
    DICT = {'BBI': bbi}

    return pd.DataFrame(DICT)


def QA_indicator_MFI(DataFrame, N=14):
    """
    资金指标
    TYP := (HIGH + LOW + CLOSE)/3;
    V1:=SUM(IF(TYP>REF(TYP,1),TYP*VOL,0),N)/SUM(IF(TYP<REF(TYP,1),TYP*VOL,0),N);
    MFI:100-(100/(1+V1));
    赋值: (最高价 + 最低价 + 收盘价)/3
    V1赋值:如果TYP>1日前的TYP,返回TYP*成交量(手),否则返回0的N日累和/如果TYP<1日前的TYP,返回TYP*成交量(手),否则返回0的N日累和
    输出资金流量指标:100-(100/(1+V1))
    """
    C = DataFrame['close']
    H = DataFrame['high']
    L = DataFrame['low']
    VOL = DataFrame['volume']
    TYP = (C + H + L) / 3
    V1 = SUM(IF(TYP > REF(TYP, 1), TYP * VOL, 0), N) / \
         SUM(IF(TYP < REF(TYP, 1), TYP * VOL, 0), N)
    mfi = 100 - (100 / (1 + V1))
    DICT = {'MFI': mfi}

    return pd.DataFrame(DICT)


def QA_indicator_ATR(DataFrame, N=14):
    """
    输出TR:(最高价-最低价)和昨收-最高价的绝对值的较大值和昨收-最低价的绝对值的较大值
    输出真实波幅:TR的N日简单移动平均
    算法：今日振幅、今日最高与昨收差价、今日最低与昨收差价中的最大值，为真实波幅，求真实波幅的N日移动平均

    参数：N　天数，一般取14

    """
    C = DataFrame['close']
    H = DataFrame['high']
    L = DataFrame['low']
    TR = MAX(MAX((H - L), ABS(REF(C, 1) - H)), ABS(REF(C, 1) - L))
    atr = MA(TR, N)
    return pd.DataFrame({'TR': TR, 'ATR': atr})


def QA_indicator_SKDJ(DataFrame, N=9, M=3):
    """
    1.指标>80 时，回档机率大；指标<20 时，反弹机率大；
    2.K在20左右向上交叉D时，视为买进信号参考；
    3.K在80左右向下交叉D时，视为卖出信号参考；
    4.SKDJ波动于50左右的任何讯号，其作用不大。

    """
    CLOSE = DataFrame['close']
    LOWV = LLV(DataFrame['low'], N)
    HIGHV = HHV(DataFrame['high'], N)
    RSV = EMA((CLOSE - LOWV) / (HIGHV - LOWV) * 100, M)
    K = EMA(RSV, M)
    D = MA(K, M)
    DICT = {'RSV': RSV, 'SKDJ_K': K, 'SKDJ_D': D}

    return pd.DataFrame(DICT)


def QA_indicator_DDI(DataFrame, N=13, N1=26, M=1, M1=5):
    """
    '方向标准离差指数'
    分析DDI柱状线，由红变绿(正变负)，卖出信号参考；由绿变红，买入信号参考。
    """

    H = DataFrame['high']
    L = DataFrame['low']
    DMZ = IF((H + L) > (REF(H, 1) + REF(L, 1)),
             MAX(ABS(H - REF(H, 1)), ABS(L - REF(L, 1))), 0)
    DMF = IF((H + L) < (REF(H, 1) + REF(L, 1)),
             MAX(ABS(H - REF(H, 1)), ABS(L - REF(L, 1))), 0)
    DIZ = SUM(DMZ, N) / (SUM(DMZ, N) + SUM(DMF, N))
    DIF = SUM(DMF, N) / (SUM(DMF, N) + SUM(DMZ, N))
    ddi = DIZ - DIF
    ADDI = SMA(ddi, N1, M)
    AD = MA(ADDI, M1)
    DICT = {'DDI': ddi, 'ADDI': ADDI, 'AD': AD}

    return pd.DataFrame(DICT)


def QA_indicator_shadow(DataFrame):
    """
    上下影线指标
    """
    return {
        'LOW': lower_shadow(DataFrame), 'UP': upper_shadow(DataFrame),
        'BODY': body(DataFrame), 'BODY_ABS': body_abs(DataFrame), 'PRICE_PCG': price_pcg(DataFrame)
    }


def lower_shadow(DataFrame):  # 下影线
    return abs(DataFrame.low - MIN(DataFrame.open, DataFrame.close))


def upper_shadow(DataFrame):  # 上影线
    return abs(DataFrame.high - MAX(DataFrame.open, DataFrame.close))


def body_abs(DataFrame):
    return abs(DataFrame.open - DataFrame.close)


def body(DataFrame):
    return DataFrame.close - DataFrame.open


def price_pcg(DataFrame):
    return body(DataFrame) / DataFrame.open


def amplitude(DataFrame):
    return (DataFrame.high - DataFrame.low) / DataFrame.low


"""

6.	大盘指标
通过涨跌家数研究大盘指数的走势
涨跌比率 ADR
绝对幅度指标 ABI
新三价率 TBR
腾落指数 ADL
广量冲力指标
指数平滑广量 STIX
"""

"""

7.	个人指标
下一个交易日涨跌
"""


def QA_indicator_LABEL(DataFrame, N=-1):
    """
    获取后N日涨跌
    N: 当前close与N日后的CLOSE比较
    """

    C = DataFrame['close']
    C_NEXT = REF(C, N)
    L = IF(C < C_NEXT, 1, 0)
    DICT = {'LABEL': L}
    return pd.DataFrame(DICT)


def QA_indicator_LABEL_LEVEL(DataFrame, N=-1, ratio=0.1):
    """
    获取当前到后N日内的涨跌幅度档位
    L0: 后N日内
    N: 当前close与N日后的CLOSE比较
    """

    C = DataFrame['close']
    C_NEXT = REF(C, N)
    L = IF(C < C_NEXT, 1, 0)
    DICT = {'LABEL': L}
    return pd.DataFrame(DICT)


def QA_indicator_Triangle(DataFrame, N=10):
    '''
    三角支撑
    以20日均线为斜边，5日均线构成钝角两个边
    在突破处触发买入信号
    :param DataFrame:
    :return:
    '''
    CLOSE = DataFrame['close']
    VOLUME = DataFrame['volume']
    MA5 = MA(CLOSE, 5)
    MA10 = MA(CLOSE, 10)
    MA20 = MA(CLOSE, 20)
    MA30 = MA(CLOSE, 30)

    UP = IFAND(GREAT(MA10, MA20), GREAT(MA20, MA30), 1, 0)
    DIF5_20 = MA5 - MA20
    DIF20_30 = MA20 - MA30
    N_up = IFAND(LLV(DIF5_20, N=N) > 0, LLV(DIF20_30, N=N) > 0, 1, 0)  # N日内5日均线在20日均线上方
    U = IFAND(MA5 > REF(MA5, N=1), REF(MA5, N=1) < REF(MA5, N=2), 1, 0)  # U型
    # U = IF(MA5 > 0, 1, 0)  # 相当于True
    B = IFAND(N_up, U, 1, 0)
    S = IF(DIF5_20 < 0, 1, 0)
    DICT = {'CLOSE': CLOSE, 'VOLUME': VOLUME, 'UP': UP, 'B': B, 'S': S, 'MA5': MA5, 'MA20': MA20, 'MA30': MA30}
    return pd.DataFrame(DICT)


def QA_indicator_BAR_BLZ(DataFrame, N=3, RANGE=0.05, V_RATIO=1.1):
    '''
    找到避雷针形态的bar
    :param DataFrame:
    :return:
    '''
    C = DataFrame['close']
    O = DataFrame['open']
    H = DataFrame['high']
    L = DataFrame['low']
    VOLUME = DataFrame['volume']
    FL = IF(VOLUME / REF(VOLUME, N=1) > V_RATIO, 1, 0)
    G = IFAND(C < O, ((H - L) / L) > RANGE, 1, 0)
    G_FL = IFAND(FL, G, 1, 0)
    NEW_HIGH = IFAND(H >= HHV(H, N=200), G_FL, 1, 0)
    G_BAR = O - C
    UP_SHADOW = H - O
    DN_SHADOW = C - L
    R = UP_SHADOW - N * (G_BAR + DN_SHADOW)
    BLZ = IFAND(NEW_HIGH, R > 0, 1, 0)
    DICT = {'CLOSE': C, 'VOLUME': VOLUME, 'BLZ': BLZ}
    return pd.DataFrame(DICT)


def QA_indicator_UP_SERIES(DataFrame, N=10):
    '''
    多头排列，回踩20日均线，且不踩破
    多头排列：10日均线、20日均线、30日均线均在各自上方
    回踩20日均线：close与20日均线的diff呈U型
    :param DataFrame:
    :return:
    '''
    CLOSE = DataFrame['close']
    VOLUME = DataFrame['volume']
    MA5 = MA(CLOSE, 5)
    MA10 = MA(CLOSE, 10)
    MA20 = MA(CLOSE, 20)
    MA30 = MA(CLOSE, 30)
    MA40 = MA(CLOSE, 40)
    MA50 = MA(CLOSE, 50)
    MA60 = MA(CLOSE, 60)

    UP = IFAND(GREAT(MA10, MA20), GREAT(MA20, MA30), 1, 0)
    DIF5_20 = MA5 - MA20
    DIF20_30 = MA20 - MA30
    N_up = IFAND(LLV(DIF5_20, N=N) > 0, LLV(DIF20_30, N=N) > 0, 1, 0)  # N日内5日均线在20日均线上方
    U = IFAND(MA5 > REF(MA5, N=1), REF(MA5, N=1) < REF(MA5, N=2), 1, 0)  # U型
    # U = IF(MA5 > 0, 1, 0)  # 相当于True
    B = IFAND(N_up, U, 1, 0)
    S = IF(DIF5_20 < 0, 1, 0)
    DICT = {'CLOSE': CLOSE, 'VOLUME': VOLUME, 'UP': UP, 'B': B, 'S': S, 'MA5': MA5, 'MA20': MA20, 'MA30': MA30}
    return pd.DataFrame(DICT)


def QA_indicator_MACD_QTDS(DataFrame, short=9, long=26, mid=13, N=10):
    '''
    MACD蜻蜓点水（个人命名）：右侧交易，属于判断主升浪
    以MACD为基础，当DIFF和DEA均在0轴上方，且DIFF > DEA，当DIFF逐渐贴近DEA，且不击穿，再次抬头时，犹如蜻蜓点水。
    这里可以加几条限制，如DEA处于上升趋势，DIFF是否击穿DEA，量能是否放大，分时图是否存在拉升抛售现象等
    :param DataFrame:
    :return:
    '''
    CLOSE = DataFrame['close']
    VOLUME = DataFrame['volume']
    DIF = EMA(CLOSE, short) - EMA(CLOSE, long)
    DEA = EMA(DIF, mid)
    MACD = (DIF - DEA) * 2
    DEA_RED = IF(LLV(DEA, N=N) > 0, 1, 0)  # N日内DEA>0
    BAR_RED = IF(LLV(MACD, N=N) > 0, 1, 0)  # N日内MACD红柱
    # BAR_RED = IF(LLV(DEA, N=N) > 0, 1, 0)  # 使用金叉时不能保证MACD》0
    BAR_DIF = DIFF(DIFF(MACD, N=1), N=1)
    BAR_UP = LAST(GREAT(BAR_DIF, 0), N1=3, N2=1)  # N1日内均满足上升趋势
    U_SHAPE = IFAND(MACD > REF(MACD, N=1), REF(MACD, N=1) < REF(MACD, N=2), 1, 0)  # U型BAR
    U_CROSS = CROSS(DIF, DEA)  # 加入金叉
    U = IFOR(U_SHAPE, U_CROSS, 1, 0)
    # B = IFAND(IFAND(DEA_RED, BAR_RED, 1, 0), U_SHAPE, 1, 0)  #
    B = IFAND(IFAND(DEA_RED, BAR_RED, 1, 0), U, 1, 0)  # 使用金叉
    DICT = {'CLOSE': CLOSE, 'VOLUME': VOLUME, 'BAR_UP': BAR_UP, 'DEA_RED': DEA_RED,
            'U_SHAPE': U_SHAPE, 'MACD': MACD, 'DIF': DIF, 'DEA': DEA, 'B': B}
    return pd.DataFrame(DICT)


'''
网格交易策略所需指标
'''


def QA_indicator_GRID(DataFrame, N=20):
    C = DataFrame['close']
    H = DataFrame['high']
    L = DataFrame['low']
    VWAP = DataFrame['amount'] / DataFrame['volume'] / 100
    TR = MAX(MAX((H - L), ABS(REF(C, 1) - H)), ABS(REF(C, 1) - L))
    ATR = MA(TR, N)
    MID_C = MA(C, N)
    STD_C = STD(C, N)
    MID_VWAP = MA(VWAP, N)
    STD_VWAP = STD(VWAP, N)
    DICT = {'CLOSE': C, 'VWAP': VWAP, 'MID_C': MID_C, 'STD_C': STD_C, 'MID_V': MID_VWAP, 'STD_V': STD_VWAP, 'ATR': ATR}
    return pd.DataFrame(DICT)


'''
海龟交易策略所需指标
'''


def QA_indicator_Turtle(DataFrame, N_UP=55, N_DN=20, N_S_MA=10, N_L_MA=60, N_ATR=20):
    C = DataFrame['close']
    H = DataFrame['high']
    L = DataFrame['low']
    VWAP = DataFrame['amount'] / DataFrame['volume'] / 100
    # UP_LINE = HHV(H, N_UP)
    # DN_LINE = LLV(L, N_DN)
    UP_LINE = HHV(C, N_UP)  # C or H?
    DN_LINE = LLV(C, N_DN)
    TR = MAX(MAX((H - L), ABS(REF(C, 1) - H)), ABS(REF(C, 1) - L))
    ATR = MA(TR, N_ATR)
    S_MA = MA(C, N_S_MA)
    L_MA = MA(C, N_L_MA)
    DIFF = S_MA - L_MA
    DICT = {'CLOSE': C, 'VWAP': VWAP, 'UP': UP_LINE, 'DN': DN_LINE, 'S_MA': S_MA, 'L_MA': L_MA, 'DIFF': DIFF,
            'ATR': ATR}
    return pd.DataFrame(DICT)


'''
双均线所需指标
'''


def QA_indicator_DoubleMA(DataFrame, N_S_MA=10, N_L_MA=60):
    C = DataFrame['close']
    VWAP = DataFrame['amount'] / DataFrame['volume'] / 100
    S_MA = MA(C, N_S_MA)
    L_MA = MA(C, N_L_MA)
    JC = CROSS(S_MA, L_MA)
    SC = CROSS(L_MA, S_MA)
    DICT = {'CLOSE': C, 'VWAP': VWAP, 'S_MA': S_MA, 'L_MA': L_MA, 'JC': JC, 'SC': SC}
    return pd.DataFrame(DICT)


'''
以布林带为基础构置网格线，用于网格交易策略
'''


def QA_indicator_BOLL_GRID(DataFrame, N=20, P1=2, P2=3):
    C = DataFrame['close']
    MID = MA(C, N)
    UB1 = MID + P1 * STD(C, N)
    LB1 = MID - P1 * STD(C, N)
    UB2 = MID + P2 * STD(C, N)
    LB2 = MID - P2 * STD(C, N)
    DICT = {'CLOSE': C, 'BOLL': MID, 'UB1': UB1, 'LB1': LB1, 'UB2': UB2, 'LB2': LB2}

    return pd.DataFrame(DICT)


def QA_indicator_warning(DataFrame, N=10):
    '''
    右侧交易的预警公式，参考one note 策略1
    N = 2 120 10
    HLC = REF(MA((HIGH + LOW + CLOSE) / 3, N), 1)
    HV = EMA(HHV(HIGH, N), 3)
    MA1 = MA(CLOSE, 1)
    WEKS = EMA(HLC * 2 - HV), 3)
    WARN = CROSS(MA1, WEKS)
    :param Dataframe:
    :param N:
    :return:
    '''

    CLOSE = DataFrame['close']
    HIGH = DataFrame['high']
    LOW = DataFrame['low']
    HLC = REF(MA((HIGH + LOW + CLOSE) / 3, N), 1)
    HV = EMA(HHV(HIGH, N), 3)
    MA1 = MA(CLOSE, 1)
    WEKS = EMA(HLC * 2 - HV, 3)
    WARN = CROSS(MA1, WEKS)
    return pd.DataFrame({'WARN': WARN})


def QA_indicator_beili(DataFrame, valid_bars=3, macd_limit=0.2):
    '''
    此策略在下跌阶段容易出现买入信号，需要结合其他策略进行分析
    在上涨和下跌趋势下出现的信号不准确
    在横盘状态出现的信号一般比较准确

    第1种解决方案
    高点的定义：分别大于前后2根K线的值。
    低点的定义：分别小于前后2根K线的值。
    所以一个背离思路就可以这样来表述：
    采用前面高点的定义方式，如果20个周期内存在两个收盘价高点，并且后一个比前一个更高，但是这两个高点对应的MACD连续红柱面积，后一个比前一个小，则认为是顶背离。
    DIFF:=EMA(C,12) – EMA(CLOSE,26);
    DEA:=EMA(DIFF,9);
    MACD:=2*(DIFF-DEA);
    HWAVE:=H>REF(H,1) && H>REF(H,2) && H>REFX(H,1) && H>REFX(H,2);
    COUNTH:=REF(COUNT(HWAVE,20),2);
    NH1:=REF(BARSLAST(HWAVE),2)+2;
    NH2:=REF(SUMBARS(HWAVE,2)-1,2)+2;
    HH1:=REF(C,NH1);
    HH2:=REF(C,NH2);
    MACD1:=REF(MACD,NH1);
    MACD2:=REF(MACD,NH2);
    顶背离:COUNTH>=2 && HH1>HH2 && MACD1<MACD2,NODRAW;
    DRAWICON(顶背离,H,’ICO5′);

     第2种解决方案
    高点定义：MACD红柱区间的最高价；
    低点定义：MACD绿柱区间的最低价；
    背离思路可以表述为：
    当前MACD小于0，前一个红柱区间内的最高价比更前一个红柱区间的最高价高，但是这两个最高价对应的MACD关系相反。

    DIFF:=EMA(C,12) – EMA(CLOSE,26);
    DEA:=EMA(DIFF,9);
    MACD:=2*(DIFF-DEA);
    UPCOND:=CROSS(DIFF,DEA);
    DOWNCOND:=CROSSDOWN(DIFF,DEA);
    END_N1:=SUMBARS(DOWNCOND,1);
    RANGE_N1:=REF(SUMBARS(UPCOND,1),END_N1);
    END_N2:=SUMBARS(DOWNCOND,2);
    RANGE_N2:=REF(SUMBARS(UPCOND,1),END_N2);
    HH1:=REF(HHV(H,RANGE_N1),END_N1);
    HH2:=REF(HHV(H,RANGE_N2),END_N2);
    MACD1:=REF(REF(MACD,HHVBARS(H,RANGE_N1)),END_N1);
    MACD2:=REF(REF(MACD,HHVBARS(H,RANGE_N2)),END_N2);
    顶背离:=CROSS(0,MACD) && HH1>HH2 && MACD1<MACD2;
    DRAWICON(顶背离,H,’ICO5′);

    第3种解决方案
    其实与第二种方案类似，仍然使用MACD红柱区间最高价判断价格趋势。
    但是，这一次，我们找的是红柱区间MACD的最大值来判断MACD的趋势，而不是用最高价对应的那两个MACD值来判断。

    DIFF:=EMA(C,12) – EMA(CLOSE,26);
    DEA:=EMA(DIFF,9);
    MACD:=2*(DIFF-DEA);
    UPCOND:=CROSS(DIFF,DEA);
    DOWNCOND:=CROSSDOWN(DIFF,DEA);
    END_N1:=SUMBARS(DOWNCOND,1);
    RANGE_N1:=REF(SUMBARS(UPCOND,1),END_N1);
    END_N2:=SUMBARS(DOWNCOND,2);
    RANGE_N2:=REF(SUMBARS(UPCOND,1),END_N2);
    HH1:=REF(HHV(H,RANGE_N1),END_N1);
    HH2:=REF(HHV(H,RANGE_N2),END_N2);
    MACD1:=REF(HHV(MACD,RANGE_N1),END_N1);
    MACD2:=REF(HHV(MACD,RANGE_N2),END_N2);
    顶背离:=CROSS(0,MACD) && HH1>HH2 && MACD1<MACD2; DRAWICON(顶背离,H,’ICO5′);

    第4种解决方案
    用MACD红柱区间最高价判断价格趋势，用红柱区间的面积判断MACD的趋势。
    DIFF:=EMA(C,12) – EMA(CLOSE,26);
    DEA:=EMA(DIFF,9);
    MACD:=2*(DIFF-DEA);
    UPCOND:=CROSS(DIFF,DEA);
    DOWNCOND:=CROSSDOWN(DIFF,DEA);
    END_N1:=SUMBARS(DOWNCOND,1);
    RANGE_N1:=REF(SUMBARS(UPCOND,1),END_N1);
    END_N2:=SUMBARS(DOWNCOND,2);
    RANGE_N2:=REF(SUMBARS(UPCOND,1),END_N2);
    HH1:=REF(HHV(H,RANGE_N1),END_N1);
    HH2:=REF(HHV(H,RANGE_N2),END_N2);
    MACD1:=REF(SUM(MACD,RANGE_N1),END_N1);
    MACD2:=REF(SUM(MACD,RANGE_N2),END_N2);
    顶背离:=CROSS(0,MACD) && HH1>HH2 && MACD1<MACD2;
    DRAWICON(顶背离,H,’ICO5′);

    这里采用第3种方案
    :param DataFrame:
    :param valid_bars: macd柱的最小个数，小于此值的区间为无效
    :param macd_limit: 区间内macd极值的限值，小于此值的区间无效
    :return:
    '''

    C = DataFrame['close']
    H = DataFrame['high']
    L = DataFrame['low']
    DIFF = EMA(C, 12) - EMA(C, 26)
    DEA = EMA(DIFF, 9)
    MACD = 2 * (DIFF - DEA)

    # 顶背离
    UPCOND = CROSS(DIFF, DEA)
    DOWNCOND = CROSS(DEA, DIFF)

    df = pd.DataFrame({'CLOSE': C, 'H': H, 'L': L, 'DIFF': DIFF, 'DEA': DEA, 'MACD': MACD,
                       'JC': UPCOND, 'SC': DOWNCOND, 'H_BL': 0, 'L_BL': 0, 'VALID': 0,
                       'MAX_MACD': 0, 'MAX_DIFF': 0, 'MAX_HIGH': 0, 'MAX_CLOSE': 0, 'AREA_MACD': 0,
                       'MIN_MACD': 0, 'MIN_DIFF': 0, 'MIN_LOW': 0, 'MIN_CLOSE': 0})
    df_tmp = pd.DataFrame(columns=df.columns)
    for index, row in df.iterrows():
        if row.JC:
            if df_tmp.shape[0] > valid_bars and np.abs(df_tmp.MACD.min()) > macd_limit:  # 有效柱数
                df.loc[index, 'MIN_MACD'] = df_tmp.MACD.min()
                df.loc[index, 'MIN_DIFF'] = df_tmp.DIFF.min()
                df.loc[index, 'MIN_LOW'] = df_tmp.L.min()
                df.loc[index, 'MIN_CLOSE'] = df_tmp.CLOSE.min()
                df.loc[index, 'AREA_MACD'] = np.abs(df_tmp.MACD.sum())
                df.loc[index, 'VALID'] = 1
            df_tmp = pd.DataFrame(columns=df.columns)
            df_tmp = df_tmp.append(row)
        elif row.SC:
            # 取红柱时，死叉日MACD为负，不要此柱
            if df_tmp.shape[0] > valid_bars and np.abs(df_tmp.MACD.min()) > macd_limit:
                df.loc[index, 'MAX_MACD'] = df_tmp.MACD.max()
                df.loc[index, 'MAX_DIFF'] = df_tmp.DIFF.max()
                df.loc[index, 'MAX_HIGH'] = df_tmp.H.max()
                df.loc[index, 'MAX_CLOSE'] = df_tmp.CLOSE.max()
                df.loc[index, 'AREA_MACD'] = df_tmp.MACD.sum()
                df.loc[index, 'VALID'] = 1
            df_tmp = pd.DataFrame(columns=df.columns)
            df_tmp = df_tmp.append(row)
        else:
            if not df_tmp.empty:
                df_tmp = df_tmp.append(row)

    last_JC = pd.Series()
    last_SC = pd.Series()
    for index, row in df.iterrows():
        if row.JC and row.VALID:
            if last_JC.empty:
                last_JC = row
            else:
                if last_JC.MIN_LOW > row.MIN_LOW and last_JC.MIN_MACD < row.MIN_MACD:
                    df.loc[index, 'L_BL'] += 1
                if last_JC.MIN_LOW > row.MIN_LOW and last_JC.MIN_DIFF < row.MIN_DIFF:
                    df.loc[index, 'L_BL'] += 1
                if last_JC.MIN_LOW > row.MIN_LOW and last_JC.AREA_MACD > row.AREA_MACD:
                    df.loc[index, 'L_BL'] += 1
        elif row.SC and row.VALID:
            if last_SC.empty:
                last_SC = row
            else:
                if last_SC.MAX_HIGH < row.MAX_HIGH and last_SC.MAX_MACD > row.MAX_MACD:
                    df.loc[index, 'H_BL'] += 1
                if last_SC.MAX_HIGH < row.MAX_HIGH and last_SC.MAX_DIFF > row.MAX_DIFF:
                    df.loc[index, 'H_BL'] += 1
                if last_SC.MAX_HIGH < row.MAX_HIGH and last_SC.AREA_MACD > row.AREA_MACD:
                    df.loc[index, 'H_BL'] += 1

    # END_N1 = SUMBARS(DOWNCOND, 1)
    # TMP = SUMBARS(UPCOND, 1)
    # RANGE_N1 = REF(SUMBARS(UPCOND, 1), END_N1)
    # END_N2 = SUMBARS(DOWNCOND, 2)
    # RANGE_N2 = REF(SUMBARS(UPCOND, 1), END_N2)
    # HH1 = REF(HHV(H, RANGE_N1), END_N1)
    # HH2 = REF(HHV(H, RANGE_N2), END_N2)
    # MACD1 = REF(HHV(MACD, RANGE_N1), END_N1)
    # MACD2 = REF(HHV(MACD, RANGE_N2), END_N2)
    # H_BL = IFAND(CROSS(0, MACD), IFAND(HH1 > HH2, MACD1 < MACD2, True, False),1, 0)
    #
    # # 底背离
    # END_N1_L = SUMBARS(DOWNCOND, 1)
    # RANGE_N1_L = REF(SUMBARS(UPCOND, 1), END_N1_L)
    # END_N2_L = SUMBARS(DOWNCOND, 2)
    # RANGE_N2_L = REF(SUMBARS(UPCOND, 1), END_N2_L)
    # HH1_L = REF(LLV(L, RANGE_N1_L), END_N1_L)
    # HH2_L = REF(LLV(L, RANGE_N2_L), END_N2_L)
    # MACD1_L = REF(LLV(MACD, RANGE_N1_L), END_N1_L)
    # MACD2_L = REF(LLV(MACD, RANGE_N2_L), END_N2_L)
    # L_BL = IFAND(CROSS(MACD, 0), IFAND(HH1_L < HH2_L, MACD1_L > MACD2_L, True, False), 1, 0)

    return df


def QA_indicator_right(DataFrame, N=1):
    '''
    通达信右侧交易

    周J:=MA("KDJ.J#WEEK"(9,3,3) ,5),COLORFFFF00,LINETHICK2;
    STICKLINE(周J>=REF(周J,1) ,0,100,4,0),COLORCC8800;
    AA:IF(周J<=0 ,-5,0),COLOR00CCCC,LINETHICK3;
    DRAWBAND(0,RGB(250,0,0),AA,RGB(0,0,0));
    BB:IF(周J>=85 ,105,100),COLOR00CC00,LINETHICK3;
    DRAWBAND(BB,RGB(0,250,0),100,RGB(0,0,0));
    长线:MA("KDJ.J#WEEK"(9,3,3) ,5),COLORFFFF00,LINETHICK2;
    IF(周J>=REF(周J,1),周J,DRAWNULL),COLORFF00FF,LINETHICK2;
    VAR1:=(CLOSE-LLV(LOW,8))/(HHV(HIGH,8)-LLV(LOW,8))*100;
    VAR2:=EMA(VAR1,3);
    VAR3:VAR2,COLOR00FF00,LINETHICK2;
    IF(VAR2>=REF(VAR2,1),VAR2,DRAWNULL),COLORRED,LINETHICK3;
    RSV:=(CLOSE-LLV(LOW,9))/(HHV(HIGH,9)-LLV(LOW,9))*100;
    K:=SMA(RSV,3,1),COLORWHITE,LINETHICK3;
    D:=SMA(K,3,1),COLORYELLOW,LINETHICK3;
    J:=K-2*D,COLORFF00FF,LINETHICK2;
    {DRAWBAND(K,RGB(200,0,200),D,RGB(190,190,0));}
    STICKLINE(K>=D, K,D,1,0),COLORBB00DD;
    STICKLINE(K<D,K,D,1,1),COLOR00DD00;
    周K:="KDJ.K#WEEK"(9,3,3),COLORLIMAGENTA,LINETHICK2;
    周D:="KDJ.D#WEEK"(9,3,3),COLORDDDD00,LINETHICK2;
    月K:="KDJ.K#MONTH"(9,3,3),COLORGRAY;
    月D:="KDJ.D#MONTH"(9,3,3),COLORLIGRAY;
    100,COLORGREEN;
    0,COLORYELLOW;
    日金叉:IF(CROSS(K,D),5,0),COLORMAGENTA,LINETHICK2;
    DRAWBAND(日金叉,RGB(250,0,250),0,RGB(0,0,0));
    日死叉: IF(CROSS(D,K),95,100), COLOR00FF00,LINETHICK2;
    DRAWBAND(100,RGB(0,250,0),日死叉,RGB(0,0,0));
    周金叉:IF(CROSS(周K,周D),10,0),COLORRED,LINETHICK2;
    DRAWBAND(周金叉,RGB(250,0,0),0,RGB(0,0,0));
    周死叉:IF(CROSS(周D,周K),90,100), COLORFFFF00,LINETHICK2;
    DRAWBAND(100,RGB(0,250,250),周死叉,RGB(0,0,0));
    月金叉:IF(CROSS(月K,月D),15,0),COLORYELLOW,LINETHICK2;
    DRAWBAND(月金叉,RGB(250,250,0),0,RGB(0,0,0));
    月死叉:IF(CROSS(月D,月K),85,100),COLORFF0000,LINETHICK2;
    DRAWBAND(100,RGB(0,0,250),月死叉,RGB(0,0,0));
    DRAWTEXT_FIX(1,0.0,0.0,0,'★★ 浅蓝色区为周J拐点向上————右侧交易区★★底部红条为周J小于0----买入准备区★★顶部绿条为风险提示'),COLORFFFFFF;
    :param DataFrame:
    :param N:
    :return:
    '''
    # 已加载到通达信客户端
    pass